package org.summer.lawyer.pay.client.impl;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.summer.common.core.exception.ServiceException;
import org.summer.lawyer.domain.bo.payorder.PayOrderBo;
import org.summer.lawyer.domain.bo.payrefund.PayRefundBo;
import org.summer.lawyer.domain.bo.paytransfer.PayTransferBo;
import org.summer.lawyer.domain.vo.paychannel.PayChannelVo;
import org.summer.lawyer.domain.vo.payorder.PayOrderVo;
import org.summer.lawyer.domain.vo.payrefund.PayRefundVo;
import org.summer.lawyer.domain.vo.paytransfer.PayTransferVo;
import org.summer.lawyer.pay.client.PayClient;

import java.util.Map;

/**
 * 抽象类，提供模板方法
 */
@Slf4j
public abstract class AbstractPayClient implements PayClient {

    /**
     * 支付通道ID
     */
    private final Long channelId;


    protected PayChannelVo channel;

    public AbstractPayClient(PayChannelVo vo) {
        this.channelId = vo.getId();
        this.channel = vo;
    }

    //初始化
    public final void init() {
        doInit();
        log.info("[init]客户端({}) 初始化完成", getId());
    }

    /**
     * 自定义初始化
     */
    protected abstract void doInit();

    @Override
    public Long getId() {
        return channelId;
    }

    public final void refresh(PayChannelVo vo) {
        //判断是否更新
        if (vo.equals(this.channel)) {
            return;
        }
        log.info("[refresh]客户端({})发生变化，重新初始化", getId());
        this.channel = vo;
        //初始化
        this.init();
    }

    @Override
    public final PayOrderVo unifiedPay(PayOrderBo bo) {
        PayOrderVo vo;
        try {
            vo = doUnifiedPay(bo);
        } catch (ServiceException ex) {
            throw ex;
        } catch (Throwable ex) {
            log.error("[unifiedPay]客户端({}) request({}) 发起支付异常, {}", getId(), JSONUtil.toJsonStr(bo), ex.getMessage());
            throw new ServiceException("支付发生错误，请稍后重试");
        }
        return vo;
    }

    protected abstract PayOrderVo doUnifiedPay(PayOrderBo bo) throws Throwable;

    @Override
    public PayOrderVo parseOrderNotify(Map<String, String> params, String body) {
        try {
            return doParseOrderNotify(params, body);
        } catch (ServiceException ex) {
            throw ex;
        } catch (Throwable ex) {
            log.error("[parseOrderNotify]客户端({}) params({}) body({}) 解析失败, {}", getId(), params, body, ex.getMessage());
            throw new ServiceException("支付回调结果解析错误");
        }
    }

    protected abstract PayOrderVo doParseOrderNotify(Map<String, String> params, String body) throws Throwable;

    @Override
    public PayOrderVo getPayOrder(String payNo) {
        try {
            return doGetPayOrder(payNo);
        } catch (ServiceException ex) {
            throw ex;
        } catch (Throwable ex) {
            log.error("[getPayOrder]客户端({}) tradeNo({}) 查询支付订单异常, {}", getId(), payNo, ex.getMessage());
            throw new ServiceException("查询支付订单发生错误");
        }
    }

    protected abstract PayOrderVo doGetPayOrder(String payNo) throws Throwable;

    @Override
    public PayRefundVo unifiedRefund(PayRefundBo bo) {
        PayRefundVo vo;
        try {
            vo = doUnifiedRefund(bo);
        } catch (ServiceException ex) {
            throw ex;
        } catch (Throwable ex) {
            log.error("[unifiedRefund]客户端({}) request({}) 发起退款异常, {}", getId(), JSONUtil.toJsonStr(bo), ex.getMessage());
            throw new ServiceException("退款发生错误，请稍后重试");
        }

        return vo;
    }

    protected abstract PayRefundVo doUnifiedRefund(PayRefundBo bo) throws Throwable;

    @Override
    public PayRefundVo parseRefundNotify(Map<String, String> params, String body) {
        try {
            return doParseRefundNotify(params, body);
        } catch (ServiceException ex) {
            throw ex;
        } catch (Throwable ex) {
            log.error("[doParseRefundNotify]客户端({}) params({}) body({}) 解析失败, {}", getId(), params, body, ex.getMessage());
            throw new ServiceException("退款回调结果解析错误");
        }
    }

    protected abstract PayRefundVo doParseRefundNotify(Map<String, String> params, String body) throws Throwable;



    @Override
    public PayRefundVo getPayRefund(String refundNo, String payNo) {
        try {
            return doGetPayRefund(refundNo, payNo);
        }catch (ServiceException ex){
            throw ex;
        }catch (Throwable ex){
            log.error("[getPayRefund]客户端({}) refundOrderId({}) 查询退款订单异常，{}", getId(), refundNo, ex.getMessage());
            throw new ServiceException("查询退款单发生错误");
        }
    }

    protected abstract PayRefundVo doGetPayRefund(String refundNo, String payNo) throws Throwable;

    @Override
    public PayTransferVo unifiedTransfer(PayTransferBo bo) {
        PayTransferVo vo;
        try {
            vo = doUnifiedTransfer(bo);
        }catch (ServiceException ex){
            throw ex;
        }catch (Throwable ex){
            log.error("[unifiedTransfer]客户端({}) request({}) 发起转账异常， {}", getId(), JSONUtil.toJsonStr(bo), ex.getMessage());
            throw new ServiceException("转账发生错误，请稍后重试");
        }
        return vo;
    }

    protected abstract PayTransferVo doUnifiedTransfer(PayTransferBo bo) throws Throwable;


    @Override
    public PayTransferVo getPayTransfer(String transferBatchNo, String transferNo) {
        try {
            return doGetPayTransfer(transferBatchNo, transferNo);
        }catch (ServiceException ex){
            throw ex;
        }catch (Throwable ex){
            log.error("[getPayTransfer]客户端({}) transferOrderId({}) 查询转账单异常， {}", getId(), transferNo, ex.getMessage());
            throw new ServiceException("查询转账单发生错误");
        }
    }

    protected abstract PayTransferVo doGetPayTransfer(String transferBatchNo, String transferNo) throws Throwable;

    @Override
    public PayTransferVo parseTransferNotify(Map<String, String> params, String body) {
        return null;
    }

    protected abstract PayTransferVo doParseTransferNotify(Map<String, String> params, String body) throws Throwable;


}
